#pragma once

#include <iostream>
#include <functional>
#include "Mutex.hpp"
#include "Cond.hpp"
#include "Thread.hpp"
#include "Log.hpp"
#include <vector>
#include <queue>

namespace ThreadPoolModel
{

    using namespace LockMutex;
    using namespace LogModel;
    using namespace CondModule;
    using namespace ThreadMode;

    const static int num = 10;
    using thread_t = std::shared_ptr<mythread>;

    template <typename T>
    class ThreadPool
    {
    private:
        bool Emptr()
        {
            return _tack_queue.empty();
        }

        void HandlerTest()
        {
            LOG(LgoLevel::DEBUG) << "线程进入测试";
            while (true)
            {
                // 接收任务
                T t;
                {
                    LockGurd lockgurd(_lock);
                    while (Emptr())
                    {
                        _waitnum++;
                        _cond.Wait(_lock);
                        _waitnum--;
                    }
                }
                t = _tack_queue.front();
                _tack_queue.pop();

                // 执行任务
                t(); // 默认每一个线程都有这个执行方法
            }
        }

    public:
        ThreadPool(int numbre = num) : _num(number), _waitnum(0)
        {
            for (int i = 0; i < num; i++)
            {
                _threads.push_back(std::make_shared<mythread>(std::bind(&ThreadPool::HandlerTest, this)));
                LOG(LgoLevel::INFo) << _threads.back()->Name() << "线程创建成功";
            }
        }
        void InitThreadPool()
        {
        }
        void Start()
        {
            for (auto &thread : _threads)
            {
                thread->strat();
                LOG(LgoLevel::INFo) << thread->Name() << "线程加载成功";
            }
        }
        void Wait()
        {
            for (auto &thread : _threads)
            {
                thread->join();
                LOG(LgoLevel::INFo) << "线程退出";
            }
        }

        void Enqueue(T &&in)
        {
            LockGurd lockgrod(_lock);
            _tack_queue.push(std::move(in));
            if (_waitnum > 0)
            {
                _cond.Notify();
            }
        }

        ~ThreadPool()
        {
        }

    private:
        int _num;
        std::vector<thread_t> _threads; // 线程池
        std::queue<T> _tack_queue;      // 任务
        mutex _lock;                    // 锁
        Cond _cond;
        int _waitnum; // 等待的线程数
    };

}